#include "rtsp_context.h"

using namespace VLRTSP;

/**
 * @Author: CimZzz
 * @Date: 2022-01-12 23:04:09
 * 
 * 宏定义，媒体会话锁
 */
#define _RTSP_CTX_SESSION_LOCK std::lock_guard<std::mutex> sessionLock(this->sessionMutex);

/**
 * @Author: CimZzz
 * @Date: 2022-01-12 23:15:30
 * 
 * 宏定义，链接操作锁
 */
#define _RTSP_CTX_CONN_LOCK std::lock_guard<std::mutex> connectLock(this->connMutex);

/**
 * @Author: CimZzz
 * @Date: 2022-01-12 22:50:12
 * 
 * 构造函数
 */
RTSPContext::RTSPContext(): dispatcherCode(1) {

}

/**
 * @Author: CimZzz
 * @Date: 2022-01-12 22:50:16
 * 
 * 析构函数
 */
RTSPContext::~RTSPContext() {

}

/**
 * @Author: CimZzz
 * @Date: 2022-01-12 22:55:43
 * 
 * 检测媒体会话是否存在
 * @param sessionId 媒体会话 Id
 * @return 如果存在返回媒体会话指针，否则返回 nullptr
 */
std::shared_ptr<MediaSession> RTSPContext::getMediaSession(const std::string& sessionId) {
	_RTSP_CTX_SESSION_LOCK
	auto iter = this->mediaSessionMap.find(sessionId);
	if(iter != this->mediaSessionMap.end()) {
		return (*iter).second;
	}
	return nullptr;
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-14 17:13:51
 * 
 * 生成一个媒体数据分发器 Id
 * @return 媒体分发器 Id
 */
uint32_t RTSPContext::generateDispatcherId() {
	return this->dispatcherCode.nextCode();
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-14 17:48:40
 * 
 * 销毁并回收资源
 */
void RTSPContext::_destroy() {
	_RTSP_CTX_SESSION_LOCK
	_RTSP_CTX_CONN_LOCK
	this->socketMap.clear();
	this->mediaSessionMap.clear();
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-12 22:53:38
 * 
 * 添加 RTSP 链接
 * @param connection RTSP 链接
 */
void RTSPContext::_addRTSPConnection(std::shared_ptr<RTSPConnection>& connection) {
	_RTSP_CTX_CONN_LOCK
	this->socketMap[connection->getConnectionId()] = std::move(connection);
}



/**
 * @Author: CimZzz
 * @Date: 2022-01-12 23:17:00
 * 
 * 移除 RTSP 链接
 * @param connectionId 链接 Id
 */
void RTSPContext::_removeRTSPConnection(uint32_t connectionId) {
	_RTSP_CTX_CONN_LOCK
	auto iter = this->socketMap.find(connectionId);
	if(iter != this->socketMap.end()) {
		this->socketMap.erase(iter);
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-12 22:54:39
 * 
 * 添加媒体会话
 * @param session 媒体会话
 * 
 * @note 媒体会话 Id 在同一个 RTSP 服务器中必须唯一，否则将会抛出异常
 */
void RTSPContext::_addMediaSession(MediaSession* session) {
	_RTSP_CTX_SESSION_LOCK
	std::string sessionId = session->getSessionId();
	auto iter = this->mediaSessionMap.find(sessionId);
	if(iter != this->mediaSessionMap.end()) {
		throw std::string("repeat register media session");
	}
	this->mediaSessionMap[session->getSessionId()] = std::shared_ptr<MediaSession>(session);
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-14 19:14:18
 * 
 * 通过媒体资源会话 Id 和媒体资源 Id 找到媒体资源
 * @param sessionId 媒体资源会话 Id
 * @param sourceId 媒体资源 Id
 * @return 媒体资源
 */
MediaSource* RTSPContext::_findMediaSource(const std::string& sessionId, uint32_t sourceId) {
	MediaSession* session = getMediaSession(sessionId).get();
	if(session == nullptr) {
		return nullptr;
	}

	return session->findMediaSource(sourceId).get();
}